
import { ZRenderComp } from '../../../common/component/zrComp';
import { calc, hold } from '../../../common/animation/index';

import layout from '../../compute/v1/layout';
import paths from '../../compute/v4/paths';

import { load as loadWeapons, WeaponIcon } from './weaponIcon';
import { AbstractContent } from './content';

class LoadoutContent extends AbstractContent {
	z1 = {
		x : 30,
		y : 50,
		spPoint : null,
		/** @type {Radial[]} */ spMainLineAnis : [],
		/** @type {Radial[]} */ spSubLineAnis : [],
		/** @type {number[][][]} */ pointPos : [],
		/** @type {WeaponIcon[][]} */ loadouts : [],
		rectWidth : 72,
	};
	z2 = {
		x : 424,
		y : 50,
		spPoint : null,
		/** @type {Radial[]} */ spMainLineAnis : [],
		/** @type {Radial[]} */ spSubLineAnis : [],
		/** @type {number[][][]} */ pointPos : [],
		spExport : null,
		spRecycle : null,
		spBg : null,
	};

	constructor(parent, zrender, animation) {
		super(parent, zrender, animation);
		this.zlevels.push(31, 32, 33, 40);

		this.z3 = new Zone3({ parent : this });
		this.z4 = new Zone4({ parent : this });
	}

	init() {
		const { zrender, zr, z1, z2 } = this;
		const [x, y] = this.relativePos();

		const createRadial = (fromPos, toPos,
				startTime1, from1, endTime1, startTime2, from2, endTime2, nOffsetTime, lOffsetTime) => {
			const r = new Radial(this, fromPos[0], fromPos[1], toPos[0], toPos[1], 2);
			r.setParam(startTime1, from1, endTime1, startTime2, from2, endTime2, nOffsetTime, lOffsetTime);
			return r;
		}

		// 1 区: 点
		{
			const rectWidth = z1.rectWidth;
			const pointPaths = [];
			for (let xx = 0; xx <= 5; xx++) {
				z1.pointPos[xx] = [];
				z1.loadouts[xx] = [];
				let px = rectWidth*xx;
				for (let yy = 0; yy <= 3; yy++) {
					let py = rectWidth*yy;
					z1.pointPos[xx][yy] = [px + z1.x, py + z1.y];
					z1.loadouts[xx][yy] = null;
					pointPaths.push(`M${px-2},${py-2}h4v4h-4z`);
				}
			}
			z1.spPoint = this.createPathFromString(pointPaths.join(''))
				.fill(layout.colors.strokeD2)
				.position(z1.x, z1.y)
				.z(32, 0)
				.build();
		}

		// 1 区: init 动画 - 长线
		z1.spMainLineAnis.push(
			createRadial(z1.pointPos[0][0], z1.pointPos[5][0], 200,  true, 260, 400,  true, 460, 15, 30), // 上
			createRadial(z1.pointPos[0][0], z1.pointPos[0][3], 220,  true, 290, 400,  true, 470, 15, 30), // 左
			createRadial(z1.pointPos[5][0], z1.pointPos[5][3], 280,  true, 350, 440,  true, 510, 15, 30), // 右
			createRadial(z1.pointPos[0][3], z1.pointPos[5][3], 290,  true, 350, 490,  true, 550, 15, 30), // 下
		);

		// 1 区: init 动画 - 短线
		let unitWidth = z1.pointPos[1][0][0] - z1.pointPos[0][0][0];
		z1.spSubLineAnis.push(
			// 第一排横着的五个
			createRadial(z1.pointPos[0][0], z1.pointPos[1][0], 500,  true, 560, 650,  true, 710, 15, 30),
			createRadial(z1.pointPos[1][0], z1.pointPos[2][0], 550,  true, 610, 700,  true, 760, 15, 30),
			createRadial(z1.pointPos[2][0], z1.pointPos[3][0], 600,  true, 660, 750,  true, 810, 15, 30),
			createRadial(z1.pointPos[3][0], z1.pointPos[4][0], 650,  true, 710, 800,  true, 860, 15, 30),
			createRadial(z1.pointPos[4][0], z1.pointPos[5][0], 700,  true, 760, 850,  true, 910, 15, 30),

			// 第一排到第二排 竖着的 6 个
			createRadial(z1.pointPos[0][0], z1.pointPos[0][1], 500,  true, 660, 650,  true, 810, 15, 30),
			createRadial(z1.pointPos[1][0], z1.pointPos[1][1], 550,  true, 710, 700,  true, 860, 15, 30),
			createRadial(z1.pointPos[2][0], z1.pointPos[2][1], 600,  true, 760, 750,  true, 910, 15, 30),
			createRadial(z1.pointPos[3][0], z1.pointPos[3][1], 650,  true, 810, 800,  true, 960, 15, 30),
			createRadial(z1.pointPos[4][0], z1.pointPos[4][1], 700,  true, 860, 850,  true,1010, 15, 30),
			createRadial(z1.pointPos[5][0], z1.pointPos[5][1], 750,  true, 910, 900,  true,1060, 15, 30),

			// 第二排横着的五个，第四个拆成两个 (左 2/3 右 1/3)，所以一共六个
			createRadial(z1.pointPos[0][1], z1.pointPos[1][1], 600,  true, 660,1050, false,1110, 15, 30),
			createRadial(z1.pointPos[1][1], z1.pointPos[2][1], 650,  true, 710,1000, false,1060, 15, 30),
			createRadial(z1.pointPos[2][1], z1.pointPos[3][1], 700,  true, 760,1050,  true,1110, 15, 30),
			function() { // 2/3 长度
				let toPos = [...z1.pointPos[3][1]];
				toPos[0] += unitWidth * (2/3);
				return createRadial(z1.pointPos[3][1],    toPos, 750,  true, 790,1100,  true,1140, 15, 30);
			}(),
			function() { // 1/3 长度
				let fromPos = [...z1.pointPos[3][1]];
				fromPos[0] += (unitWidth * (2/3) - 2);
				return createRadial(fromPos,  z1.pointPos[4][1], 750,  true, 790,1100, false,1140, 15, 30);
			}(),
			createRadial(z1.pointPos[4][1], z1.pointPos[5][1], 720, false, 780,1070, false,1130, 15, 30),

			// 第二排到第三排 竖着的 6 个
			createRadial(z1.pointPos[0][1], z1.pointPos[0][2], 980,  true,1140,1130,  true,1290, 15, 30),
			createRadial(z1.pointPos[1][1], z1.pointPos[1][2], 930,  true,1090,1080,  true,1240, 15, 30),
			createRadial(z1.pointPos[2][1], z1.pointPos[2][2], 880,  true,1040,1030,  true,1190, 15, 30),
			createRadial(z1.pointPos[3][1], z1.pointPos[3][2], 830,  true, 990, 980,  true,1140, 15, 30),
			createRadial(z1.pointPos[4][1], z1.pointPos[4][2], 780,  true, 940, 930,  true,1090, 15, 30),
			createRadial(z1.pointPos[5][1], z1.pointPos[5][2], 730,  true, 890, 880,  true,1040, 15, 30),

			// 第三排横着的五个，第二个拆成两个 (左 2/3 右 1/3)，所以一共六个, 从左往右排, 不是按时间排
			createRadial(z1.pointPos[0][2], z1.pointPos[1][2], 900,  true, 960,1240, false,1300, 15, 30),
			function() { // 2/3 长度
				let toPos = [...z1.pointPos[1][2]];
				toPos[0] += unitWidth * (2/3);
				return createRadial(z1.pointPos[1][2],    toPos, 950,  true, 990,1210,  true,1230, 15, 30);
			}(),
			function() { // 1/3 长度
				let fromPos = [...z1.pointPos[1][2]];
				fromPos[0] += (unitWidth * (2/3) - 2);
				return createRadial(fromPos,  z1.pointPos[2][2], 970, false, 990,1190, false,1210, 15, 30);
			}(),
			createRadial(z1.pointPos[2][2], z1.pointPos[3][2], 920, false, 980,1140, false,1200, 15, 30),
			createRadial(z1.pointPos[3][2], z1.pointPos[4][2], 870, false, 930,1140,  true,1200, 15, 30),
			createRadial(z1.pointPos[4][2], z1.pointPos[5][2], 820, false, 880,1190,  true,1250, 15, 30),

			// 第三排到第四排 竖着的 6 个
			createRadial(z1.pointPos[0][2], z1.pointPos[0][3], 930,  true,1090,1080,  true,1240, 15, 30),
			createRadial(z1.pointPos[1][2], z1.pointPos[1][3], 980,  true,1140,1130,  true,1290, 15, 30),
			createRadial(z1.pointPos[2][2], z1.pointPos[2][3],1030,  true,1190,1180,  true,1340, 15, 30),
			createRadial(z1.pointPos[3][2], z1.pointPos[3][3],1080,  true,1240,1230,  true,1390, 15, 30),
			createRadial(z1.pointPos[4][2], z1.pointPos[4][3],1130,  true,1290,1280,  true,1440, 15, 30),
			createRadial(z1.pointPos[5][2], z1.pointPos[5][3],1180,  true,1340,1330,  true,1490, 15, 30),

			// 第四排横着的五个
			createRadial(z1.pointPos[0][3], z1.pointPos[1][3],1090,  true,1150,1250,  true,1310, 15, 30),
			createRadial(z1.pointPos[1][3], z1.pointPos[2][3],1140,  true,1200,1300,  true,1360, 15, 30),
			createRadial(z1.pointPos[2][3], z1.pointPos[3][3],1190,  true,1250,1350,  true,1410, 15, 30),
			createRadial(z1.pointPos[3][3], z1.pointPos[4][3],1240,  true,1300,1400,  true,1460, 15, 30),
			createRadial(z1.pointPos[4][3], z1.pointPos[5][3],1290,  true,1350,1450,  true,1510, 15, 30),
		);

		// 1 区: 放道具图标

		const createZ1Icon = (x, y, iconDef) => {
			const width = z1.rectWidth;
			const scale = ((width * 0.8) / Math.max(iconDef.width, iconDef.height)) | 0;
			const offsetX = (width - scale * iconDef.width) / 2;
			const offsetY = (width - scale * iconDef.height) / 2;

			return new WeaponIcon({
				parent : this,
				iconDef, scale,
				x : z1.pointPos[x][y][0] + offsetX,
				y : z1.pointPos[x][y][1] + offsetY,
				zIndex : 32, z : 250,
			});
		}
		loadWeapons(this.getContext()).then(bundles => {
			this.bundles = bundles;
			bundles = bundles.filter(b => b.category == 'megaman');
			if (bundles.length == 0) {
				return;
			}

			// 我们一共有 15 个空位
			// 前两行放 weapon, 最后一行放 prop
			const weaponCount = ((Math.random() * 7) | 0) + 3;
			const weaponList = bundles.map(b => b.weapons).reduce((p, v) => p.concat(v), []).slice(0, weaponCount);
			weaponList.sort(() => Math.random() > 0.5 ? 1 : -1);
			weaponList.forEach((w, index) => {
				let x = index % 5;
				let y = (index / 5) | 0;
				z1.loadouts[x][y] = createZ1Icon(x, y, w);
			});

			const propCount = ((Math.random() * 4) | 0) + 1;
			const propList = bundles.map(b => b.props).reduce((p, v) => p.concat(v), []).slice(0, propCount);
			propList.sort(() => Math.random() > 0.5 ? 1 : -1);
			propList.forEach((w, index) => {
				let x = 4 - index;
				let y = 2;
				z1.loadouts[x][y] = createZ1Icon(x, y, w);
			});
		})

		// 2 区: 点
		{
			const rectWidth = z1.rectWidth;
			const ww = rectWidth - 4;
			const pointPaths = [];
			const bgPaths = [];
			for (let xx = 0; xx <= 1; xx++) {
				z2.pointPos[xx] = [];
				let px = rectWidth*xx;
				for (let yy = 0; yy <= 2; yy++) {
					let py = rectWidth*yy;
					z2.pointPos[xx][yy] = [px + z2.x, py + z2.y];
					pointPaths.push(`M${px-2},${py-2}h4v4h-4Z`);
					xx==1 || yy==2 || bgPaths.push(`M${px+2},${py+2}h${ww}v${ww}h-${ww}Z`);
				}
			}
			z2.spPoint = this.createPathFromString(pointPaths.join(''))
				.fill(layout.colors.strokeD2)
				.position(z2.x, z2.y)
				.z(32, 0)
				.build();
			z2.spBg = this.createPathFromString(bgPaths.join(''))
				.fill(layout.colors.strokeBgL2)
				.opacity(0.5)
				.position(z2.x, z2.y)
				.z(32, 0)
				.build();
		}

		// 2 区: init 动画 - 长线
		z2.spMainLineAnis.push(
			createRadial(z2.pointPos[0][0], z2.pointPos[1][0], 200,  true, 270, 360,  true, 430, 15, 30), // 上
			createRadial(z2.pointPos[0][0], z2.pointPos[0][2], 200,  true, 300, 380,  true, 480, 15, 30), // 左
			createRadial(z2.pointPos[1][0], z2.pointPos[1][2], 270,  true, 370, 450,  true, 550, 15, 30), // 右
			createRadial(z2.pointPos[0][2], z2.pointPos[1][2], 300,  true, 370, 500,  true, 570, 15, 30), // 下
		);

		// 2 区: init 动画 - 短线
		z2.spSubLineAnis.push(
			// 第一个方块
			createRadial(z2.pointPos[0][0], z2.pointPos[1][0], 500,  true, 560, 650,  true, 710, 15, 30), // 上
			createRadial(z2.pointPos[0][0], z2.pointPos[0][1], 500,  true, 660, 650,  true, 810, 20, 40), // 左
			createRadial(z2.pointPos[1][0], z2.pointPos[1][1], 560,  true, 720, 710,  true, 870, 20, 40), // 右
			createRadial(z2.pointPos[0][1], z2.pointPos[1][1], 660,  true, 720, 810,  true, 870, 15, 30), // 下

			// 第二个方块
			createRadial(z2.pointPos[0][1], z2.pointPos[1][1], 530,  true, 590, 680,  true, 740, 15, 30), // 上
			createRadial(z2.pointPos[0][1], z2.pointPos[0][2], 530,  true, 690, 680,  true, 840, 20, 40), // 左
			createRadial(z2.pointPos[1][1], z2.pointPos[1][2], 590,  true, 750, 740,  true, 900, 20, 40), // 右
			createRadial(z2.pointPos[0][2], z2.pointPos[1][2], 690,  true, 750, 840,  true, 900, 15, 30), // 下
		);

		// 2 区: 两个标志, 一个底
		{
			const {exports, recycle} = layout.loudoutPath;
			const xx = (z2.pointPos[0][0][0] + z2.pointPos[1][0][0]) / 2;
			const yy1 = (z2.pointPos[0][0][1] + z2.pointPos[0][1][1]) / 2;
			const yy2 = (z2.pointPos[0][1][1] + z2.pointPos[0][2][1]) / 2;

			zr.add(z2.spExport = zrender.path.createFromString(exports.path, {
				style: { fill: layout.colors.strokeD2 },
				position: [(x + xx - (exports.width) * 1.5) | 0, (y + yy1 - (exports.height) * 1.5) | 0],
				scale: [3, 3], z: 204, zlevel: 32
			}));
			zr.add(z2.spExport = zrender.path.createFromString(recycle.path, {
				style: { fill: layout.colors.strokeD2 },
				position: [(x + xx - (recycle.width) * 1.5) | 0, (y + yy2 - (recycle.height) * 1.5) | 0],
				scale: [3, 3], z: 204, zlevel: 32
			}));
		}

		// 整体去除 (不知道为什么 zrender 脑残, destination-in 用不了)
		super.init();
	}

	tick(now) {
		super.tick(now);

		if (now - this.deskAnimation.baseTime > 10000) {
			this.deskAnimation.footerSwitch();
		}
	}
}

/**
 * zlevel=32
 */
class Radial extends ZRenderComp {
	/**
	 * @param {number} x1
	 * @param {number} y1
	 * @param {number} x2
	 * @param {number} y2
	 * @param {number} lineWidth
	 */
	constructor(parent, x1, y1, x2, y2, lineWidth) {
		super(parent);
		this.useParentZRenderInstance(x1, y1);

		this.lineWidth = lineWidth;
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
	}

	init() {
		this.sps = [
			{ fill: layout.colors.strokeNormal, shadow: layout.colors.strokeBgL3, blur: 5, z: 210 },
			{ fill: layout.colors.strokeD1,     shadow: layout.colors.strokeBgL2, blur: 4, z: 209 },
			{ fill: layout.colors.strokeD2,     shadow: layout.colors.strokeBgL1, blur: 3, z: 208 }
		].map(arg =>
			this.createLine(0, 0, this.x2 - this.x1, this.y2 - this.y1)
				.stroke(arg.fill, this.lineWidth)
				.shadow(arg.shadow, arg.blur)
				.z(32, arg.z)
				.build()
		);
	}

	dstart = 0;
	dend = 0;
	nstart = 0;
	nend = 0;
	lstart = 0;
	lend = 0;
	/**
	 * @param {number} startTime1 D 颜色线段出现时的时间点
	 * @param {boolean} from1 D 颜色线段出现时从左 true; 右 false
	 * @param {number} endTime1 D 颜色线段出现动画结束的时间点
	 * @param {number} startTime2 D 颜色线段开始消失时的时间点
	 * @param {boolean} from2 D 颜色线段消失时从左 true; 右 false
	 * @param {number} endTime2 D 颜色线段消失动画结束的时间点
	 * @param {number} nOffsetTime N 颜色线段动画和 D 颜色线段动画的时间差
	 * @param {number} lOffsetTime L 颜色线段动画和 D 颜色线段动画的时间差
	 */
	setParam(startTime1, from1, endTime1, startTime2, from2, endTime2, nOffsetTime, lOffsetTime) {
		let ds = this.createAnimation('DStart').whenUpdated(v => {
			this.dstart = v.value;
			this.makeDirty(false);
		});
		let de = this.createAnimation('DEnd').whenUpdated(v => {
			this.dend = v.value;
			this.makeDirty(false);
		});
		let ns = this.createAnimation('NStart').whenUpdated(v => {
			this.nstart = v.value;
			this.makeDirty(false);
		});
		let ne = this.createAnimation('NEnd').whenUpdated(v => {
			this.nend = v.value;
			this.makeDirty(false);
		});
		let ls = this.createAnimation('LStart').whenUpdated(v => {
			this.lstart = v.value;
			this.makeDirty(false);
		});
		let le = this.createAnimation('LEnd').whenUpdated(v => {
			this.lend = v.value;
			this.makeDirty(false);
		});

		let destroySelf = () => this.destroy();
		let startTime1n = startTime1 + nOffsetTime;
		let endTime1n = endTime1 + nOffsetTime;
		let startTime2n = startTime2 - nOffsetTime;
		let endTime2n = endTime2 - nOffsetTime;
		let startTime1l = startTime1 + lOffsetTime;
		let endTime1l = endTime1 + lOffsetTime;
		let startTime2l = startTime2 - lOffsetTime;
		let endTime2l = endTime2 - lOffsetTime;
		if (from1) {
			if (from2) {
				ds.update().when(startTime2, 0).when(endTime2, 1).callback(destroySelf).commit();
				de.update().when(startTime1, 0).when(endTime1, 1).commit();
				ns.update().when(startTime1n, 0).when(endTime1n, 0).when(startTime2n, 0).when(endTime2n, 1).commit();
				ne.update().when(startTime1n, 0).when(endTime1n, 1).commit();
				ls.update().when(startTime2l, 0).when(endTime2l, 1).commit();
				le.update().when(startTime1l, 0).when(endTime1l, 1).commit();
			} else {
				ds.update().when(endTime2, 0).callback(destroySelf).commit();
				de.update().when(startTime1, 0).when(endTime1, 1).when(startTime2, 1).when(endTime2, 0).commit();
				ns.update().when(endTime2n, 0).commit();
				ne.update().when(startTime1n, 0).when(endTime1n, 1).when(startTime2n, 1).when(endTime2n, 0).commit();
				ls.update().when(startTime1l, 0).commit();
				le.update().when(startTime1l, 0).when(endTime1l, 1).when(startTime2l, 1).when(endTime2l, 0).commit();
			}
		} else {
			if (from2) {
				ds.update().when(startTime1, 1).when(endTime1, 0).when(startTime2, 0).when(endTime2, 1).callback(destroySelf).commit();
				de.update().when(startTime1, 1).commit();
				ns.update().when(startTime1n, 1).when(endTime1n, 0).when(startTime2n, 0).when(endTime2n, 1).commit();
				ne.update().when(startTime1n, 1).commit();
				ls.update().when(startTime1l, 1).when(endTime1l, 0).when(startTime2l, 0).when(endTime2l, 1).commit();
				le.update().when(startTime1l, 1).commit();
			} else {
				ds.update().when(startTime1, 1).when(endTime1, 0).when(endTime2, 0).easing(hold).callback(destroySelf).commit();
				de.update().when(startTime2, 1).when(endTime2, 0).commit();
				ns.update().when(startTime1n, 1).when(endTime1n, 0).commit();
				ne.update().when(startTime2n, 1).when(endTime2n, 0).commit();
				ls.update().when(startTime1l, 1).when(endTime1l, 0).commit();
				le.update().when(startTime2l, 1).when(endTime2l, 0).commit();
			}
		}
	}

	paint() {
		const [l, n, d] = this.sps;
		l.sp.attr({ shape : {
			x1 : calc(0, this.x2 - this.x1, this.lstart),
			y1 : calc(0, this.y2 - this.y1, this.lstart),
			x2 : calc(0, this.x2 - this.x1, this.lend),
			y2 : calc(0, this.y2 - this.y1, this.lend),
		}});
		n.sp.attr({ shape : {
			x1 : calc(0, this.x2 - this.x1, this.nstart),
			y1 : calc(0, this.y2 - this.y1, this.nstart),
			x2 : calc(0, this.x2 - this.x1, this.nend),
			y2 : calc(0, this.y2 - this.y1, this.nend),
		}});
		d.sp.attr({ shape : {
			x1 : calc(0, this.x2 - this.x1, this.dstart),
			y1 : calc(0, this.y2 - this.y1, this.dstart),
			x2 : calc(0, this.x2 - this.x1, this.dend),
			y2 : calc(0, this.y2 - this.y1, this.dend),
		}});
	}

	destroy() {
		super.destroy();
	}
}

/**
 * 动态在 zlevel=31
 * 
 * 头像能不能做成老电影的感觉
 * 1. 闪烁. 亮度随机
 * 2. 扫描线
 */
class Zone3 extends ZRenderComp {
	spIconAppearTime = 0;
	hasDestroyed = false;

	constructor(args) {
		super(args.parent);
		this.useParentZRenderInstance();
	}

	init() {
		if (z3Avatars == null) {
			z3Avatars = new Z3Avatars(this.root.context);
		}

		z3Avatars.fetchIcon('megaman')
			.then(canvas => this.createIcon(canvas)); // z = 202
	}

	/**
	 * @param {HTMLCanvasElement} canvas
	 */
	createIcon(canvas) {
		if (this.hasDestroyed) return;
		this.spIconAppearTime = Date.now();

		// const c2 = document.createElement('canvas');
		// c2.width = canvas.width;
		// c2.height = canvas.height;
		// const ctx = c2.getContext('2d');
		// ctx.drawImage(canvas, 0, 0);

		// 叠加层, 透明度 0.3, 被 spArrow 切割的
		const colorFrameArray = [];
		for (let i = 0; i < 10; i++) {
			colorFrameArray.push({ offset: i*0.1+0.01, color: '#2FC0'});
			colorFrameArray.push({ offset: i*0.1+0.05, color: '#2FC1'});
			colorFrameArray.push({ offset: i*0.1+0.09, color: '#2FC4'});
		}
		this.iScanBaseY = layout.content.height - canvas.height / 4 * 5;
		this.iImgBaseY = layout.content.height - canvas.height;
		this.iScanY = this.iScanBaseY;

		this.spScanBg = this.createImage(canvas)
			.position(0, this.iImgBaseY)
			.z(31, 203)
			.build();
		this.spScanLayer = this.createRect(canvas.width, canvas.height / 4 * 5)
			.blend('source-in')
			.opacity(0.4)
			.fillLinearGradient(0, 0, 0, 1, colorFrameArray)
			.position(0, this.iScanBaseY)
			.z(31, 203)
			.build();
		this.spIcon1 = this.createImage(canvas)
			.blend('lighten')
			.opacity(0.4)
			.position(0, this.iImgBaseY)
			.z(31, 204)
			.build();
	}

	tick(now) {
		// 扫描线
		const {iScanBaseY, iImgBaseY} = this;
		this.iScanY = calc(iScanBaseY, iImgBaseY, (now % 2000) / 2000);
		this.makeDirty(false);

		super.tick(now);
	}

	paint() {
		if (this.spIcon1) {
			this.spScanLayer.moveTo(undefined, this.iScanY);

			if (Math.random() > 0.7) {
				const lastOp = this.spIcon1.sp.style.opacity;
				const nextOp = 0.3 + Math.random() * 0.4;
				this.spIcon1.attr({ style : {opacity : (nextOp + 2*lastOp) / 3} });
			}
		}

		super.paint();
	}

	destroy() {
		this.hasDestroyed = true;
		super.destroy();
	}
}

class Z3Avatars {
	constructor(context) {
		this.avatars = [
			{
				name : 'megaman',
				height : 196,
				width : -1,
				url : '',
				canvas : null
			}
		];
		this.avatars.forEach(e => {
			e.url = context.assetPath(`assets/loadout_icon_${e.name}.png`);
		});
	}

	/**
	 * @param {string} name
	 * @returns {Promise<HTMLCanvasElement>}
	 */
	fetchIcon(name) {
		let a = this.avatars.find(el => el.name === name);
		if (a.canvas) {
			return Promise.resolve(a.canvas);
		}

		return new Promise((resolve, reject) => {
			let img = document.createElement('img');
			img.onload = () => {resolve(img);};
			img.onerror = (e) => {reject(e);};
			img.src = a.url;
		}).then(img => {
			if (a.width > 0) {
				a.height = (a.width * img.naturalHeight) / img.naturalWidth;
			} else {
				a.width = (a.height * img.naturalWidth) / img.naturalHeight;
			}
			const canvas = document.createElement('canvas');
			canvas.width = a.width;
			canvas.height = a.height;
			const ctx = canvas.getContext('2d');
			ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, a.width, a.height);
			return a.canvas = canvas;
		});
	}
};
/** @type {Z3Avatars} */
let z3Avatars;

/**
 * 静态在 zlevel=32
 * 动态在 zlevel=31/33
 */
class Zone4 extends ZRenderComp {
	main = { // 最大的菱形块
		x : 250,
		y : layout.content.height - 120,
		r : 42,
	};
	slots = [ // 3 个方形插槽
		{ x : 330, y : layout.content.height - 100, r : 24, sp : null },
		{ x : 400, y : layout.content.height - 100, r : 24, sp : null },
		{ x : 470, y : layout.content.height - 100, r : 24, sp : null }
	];
	lights = [ // 3 个灯
		{ x : 330, y : layout.content.height - 150, r : 6 },
		{ x : 400, y : layout.content.height - 150, r : 6 },
		{ x : 470, y : layout.content.height - 150, r : 6 }
	];
	lines = [ // 连接线 4 块
		{ x : 276, y : layout.content.height - 150, sp : null },
		{ x : 336, y : layout.content.height - 150, sp : null },
		{ x : 406, y : layout.content.height - 150, sp : null },
		{ x : 476, y : layout.content.height - 150, sp : null }
	];
	gear = {
		x: 430,
		y: 370,
		scale: 0.4
	};

	constructor(args) {
		super(args.parent);
		this.useParentZRenderInstance();
	}

	init() {
		// 菱形块 (动)
		const mr = this.main.r;
		const pDiamond = `M0,-${mr}L-${mr},0L0,${mr}L${mr},0Z`;
		const mag = this.iDiamond = (Math.hypot(mr, mr) * 4) | 0;
		this.spDiamond = this.createPathFromString(pDiamond)
			.stroke(layout.colors.strokeNormal, 3)
			.fill('transparent')
			.lineDash([mag / 2, mag / 2], 0)
			.shadow(layout.colors.strokeBgL1, 4)
			.position(this.main.x, this.main.y)
			.z(33, 203)
			.build();
		// 菱形块 (静)
		this.spDiamondBgs = [-16, -8, 0, 8].map(i => {
			const rr = mr + i;
			const path = `M0,-${rr}L-${rr},0L0,${rr}L${rr},0Z`;
			return this.createPathFromString(path)
				.stroke(layout.colors.strokeBg, 3)
				.fill('transparent')
				.position(this.main.x, this.main.y)
				.opacity(0.6)
				.z(32, 201)
				.build();
		});
		// 菱形块 (亮)
		this.spDiamondLts = [-16, -8, 0, 8].map(i => {
			const rr = mr + i;
			const path = `M0,-${rr}L-${rr},0L0,${rr}L${rr},0Z`;
			return this.createPathFromString(path)
				.stroke(layout.colors.yellowNormal, 3)
				.shadow(layout.colors.yellowNormal, 0)
				.fill('transparent')
				.position(this.main.x, this.main.y)
				.opacity(0.7)
				.z(33, 202)
				.build();
		});

		this.slots.forEach(slot => {
			const {r, x : sx, y : sy} = slot;
			const hr = r / 2, qr = r / 6;
			slot.sp = this.createPathFromString(
				`M-${hr}-${r}h${r}l${qr},${qr}h-4l-${qr-2}-${qr-2}h-${r-4}l-${qr-2},${qr-2}h-4l${qr}-${qr}z` // 上
				+ `M-${hr},${r}h${r}l${qr}-${qr}h-4l-${qr-2},${qr-2}h-${r-4}l-${qr-2}-${qr-2}h-4l${qr},${qr}z` // 下
				+ `M-${r}-${hr}v${r}l${qr},${qr}v-4l-${qr-2}-${qr-2}v-${r-4}l${qr-2}-${qr-2}v-4l-${qr},${qr}z` // 左
				+ `M${r}-${hr}v${r}l-${qr},${qr}v-4l${qr-2}-${qr-2}v-${r-4}l-${qr-2}-${qr-2}v-4l${qr},${qr}z`, // 右
			).fill(layout.colors.strokeD1)
				.position(sx, sy)
				.z(32, 202)
				.build();
		});
		this.spLights = this.lights.map(light => {
			const {r, x : sx, y : sy} = light;
			return this.createPolygon([0, -r], [r, 0], [0, r], [-r, 0])
				.fill(layout.colors.yellowNormal)
				.shadow(layout.colors.yellowNormal, 3)
				.position(sx, sy)
				.z(32, 202)
				.build();
		});

		const { lines } = this;
		lines[0].sp = this.createPathFromString('M0-1h40l8-8v3l-6,6l6,6v3l-8-8h-40 l4,4h-8l-6,-6L0-1z')
			.fill(layout.colors.strokeD2)
			.position(lines[0].x, lines[0].y)
			.z(32, 202)
			.build();
		const pLine = 'M6,0l-6-6v-3l8,8 h42 l8-8v3l-6,6l6,6v3l-8-8 h-42 l-8,8v-3l6-6z';
		lines[1].sp = this.createPathFromString(pLine)
			.fill(layout.colors.strokeD2)
			.position(lines[1].x, lines[1].y)
			.z(32, 202)
			.build();
		lines[2].sp = this.createPathFromString(pLine)
			.fill(layout.colors.strokeD2)
			.position(lines[2].x, lines[2].y)
			.z(32, 202)
			.build();
		lines[3].sp = this.createPathFromString('M6,0l-6-6v-3l8,8 h9 l9,9v40l-6,6v-14l4-4v-28l-7-7 h-9 l-8,8v-3l6-6z')
			.fill(layout.colors.strokeD2)
			.position(lines[3].x, lines[3].y)
			.z(32, 202)
			.build();

		// 大齿轮底
		this.spGear = this.createPathFromString(paths.gear)
			.fill(layout.colors.strokeBgD3)
			.position(this.gear.x, this.gear.y)
			.scale(this.gear.scale)
			.anchor(...paths.gearAnchor)
			.opacity(0.2)
			.z(31, 212)
			.build();
	}

	tick(now) {
		super.tick(now);

		// 菱形
		const lineDashOffset = (now >> 4) % this.iDiamond;
		this.spDiamond.attr({ style : { lineDashOffset } });

		// 菱形 (亮)
		{
			const dt = now % 2400;
			const dn = (dt / 300) | 0;
			const dx = (dt % 300) / 300 * 0.1;
			const o = [0, 0, 0, 0];
			if (dn < 4) { o[dn] = 0.6; }
			switch (dn) {
			case 1: o[0] = 0.3 - dx; break;
			case 2: o[0] = 0.2 - dx; o[1] = 0.3 - dx; break;
			case 3: o[0] = 0.1 - dx; o[1] = 0.2 - dx; o[2] = 0.3 - dx; break;
			case 4: o[1] = 0.1 - dx; o[2] = 0.2 - dx; o[3] = 0.3 - dx; break;
			case 5: o[2] = 0.1 - dx; o[3] = 0.2 - dx; break;
			case 6: o[3] = 0.1 - dx; break;
			}
			this.spDiamondLts.forEach((sp, index) => {
				const d = o[index];
				sp.attr({ style : { shadowBlur : 12 * d, opacity : d } });
			});
		}

		// 灯
		{
			const dt = now % 2250;
			const dn = (dt / 750) | 0;
			const dx = (dt % 750) / 750 * 0.4;
			const o = [0, 0, 0];
			if (dn < 3) { o[dn] = 1; }
			switch (dn) {
			case 0: o[2] = 0.4 - dx; break;
			case 1: o[0] = 0.4 - dx; break;
			case 2: o[1] = 0.4 - dx; break;
			}
			this.spLights.forEach((sp, index) => sp.attr({ style : { opacity : o[index] } }));
		}

		// 齿轮
		{
			this.spGear.rotation(this.spGear.sp.rotation + 0.004);
		}
	}
}

export {
	LoadoutContent
};
